package serveur;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.Arrays;


public class PlacerNavires implements Runnable{

	private Joueur joueur;

	public PlacerNavires(Joueur joueur) {
		this.joueur = joueur;
	}

	@Override
	public void run() {
		int navireEnCours = 0;
		boolean finPlacement = false;
		boolean isDisconnected = false;
		do{
			try {

				String message;
				String envoi = Commande.SHIP+
						joueur.getNavires().get(navireEnCours).getLongueur()+
						"/\n";
				
				System.out.print("-------------------");
				joueur.getOut().flush();
				System.out.println("-------------------");

				joueur.sendMessage(envoi);

				message = joueur.receiveMessage();

				if(message == null){
					System.err.println("Joueur déconnecté.");
					isDisconnected=true;
					int indiceP = joueur.getNumPartie();
					joueur.setPerdant(true);
					AccepterConnexion.listeParties.get(
							indiceP).getJoueurs().remove(joueur);
					break;
				}

				else{

					if(	message.startsWith(Commande.PUTSHIP) &&
							message.endsWith("/")){ 				 				

						/*	if(	message.startsWith(Commande.PUTSHIP)){*/

						String[] tabChaines = message.split("/");
						for(int j=0; j<tabChaines.length; j++){
							System.out.println("tabChaines["+j+"] = "+tabChaines[j]);
						}

						//tabChaines.length -2 selon caractère
						String[] listArg = new String[tabChaines.length -1];
						System.arraycopy(tabChaines, 1, listArg, 0, tabChaines.length-1);
						for(int j=0; j<listArg.length; j++){
							System.out.println("listArg["+j+"] = "+listArg[j]);
						}

						//int tailleBateau = tabChaines.length;
						int tailleBateau = listArg.length;
						//tailleBateau = tailleBateau-2; //on enleve la cmd + le \n
						tailleBateau = tailleBateau/2; //1 pt <=> (x,y) : 2 args

						if (tailleBateau != joueur.getNavires().get(
								navireEnCours).getLongueur()) {
							
							// Mauvais nombre de paramètres
							joueur.sendMessage(Commande.WRONG);
						}
						else {
							System.out.println("taille bateau = "+tailleBateau+"\t");

							int [][] positions = new int [tailleBateau][2];
							try{
								// Stockage des coordonneés dans un tableau
								for (int i = 0; i < tailleBateau; i++) {
									//affectation de x 

									positions[i][0] = Integer.valueOf(listArg[i*2]);

									//affectation de y
									char yChar = listArg[1+i*2].charAt(0);
									positions[i][1] = Integer.valueOf((int)yChar - 65);

									System.out.print("  ("+positions[i][0] + ";" +
											positions[i][1]+") ");
								}
								System.out.println();
								
							}catch(NumberFormatException nfe){
								joueur.sendMessage(Commande.WRONG);
								continue;
							}

							// On vérifie que les positions sont bien dans le tableau
							// et que les valeurs sont alignées
							// et que ça ne touche pas un autre bateau
							if (isValidPositions(positions, navireEnCours) && positionsAreAlign(positions) &&
									shipIsAlign(positions) && checkPositionOtherNavires(positions, navireEnCours)) {

								// On enregistre le bateau
								joueur.getNavires().get(navireEnCours).setxA(positions[0][0]);
								joueur.getNavires().get(navireEnCours).setyA(positions[0][1]);
								joueur.getNavires().get(navireEnCours).setxB(positions[positions.length-1][0]);
								joueur.getNavires().get(navireEnCours).setyB(positions[positions.length-1][1]);

								// on incrémente le compteur
								navireEnCours++;

								// on envoie le message ok
								joueur.sendMessage(Commande.OK);


							} else {
								System.out.println("Erreur");
								joueur.sendMessage(Commande.WRONG);

							}
						}

						if(navireEnCours == joueur.getNavires().size()){
							finPlacement=true;
						}

					} else {
						//Commande invalide 
						joueur.sendMessage(Commande.WRONG);

					}
					Thread.sleep(100);
				}
			}catch(SocketTimeoutException ste){
				System.err.println("Joueur inactif.");
				
				int indiceP = joueur.getNumPartie();
				AccepterConnexion.listeParties.get(
						indiceP).getJoueurs().remove(joueur);
				
				isDisconnected = true;
				ste.printStackTrace();

			}catch (IOException e) {
				System.err.println("Erreur placement!");
				e.printStackTrace();

			} catch (InterruptedException e) {
				System.err.println("Thread de placement interrompu/Sleep.");
				Thread.currentThread().interrupt();
				e.printStackTrace();
			}

		}while(!finPlacement && !isDisconnected);

		AccepterConnexion.listeParties.get(
				joueur.getNumPartie() ).placementIsOk(this.joueur);

		if(!isDisconnected){
			try {
				String allyourbase = Commande.ALLYOURBASE + "\n";
				joueur.sendMessage(allyourbase);
			} catch (IOException e) {
				System.err.println("Erreur envoi commande allyourbase");
				e.printStackTrace();
			}
		}else{
			Thread.currentThread().interrupt();
		}
	}

	//si x et y sont entre 0 et 15 renvoie vrai sinon renvoie faux
	private boolean isValidPositions (int[][] positions, int currentNavire){
		for (int i = 0; i < positions.length; i++) {
			if (positions[i][0] < 0 || positions[i][0] > 15) {
				return false;
			}
			else if (positions[i][1] < 0 || positions[i][1] > 15) {
				return false;
			}
		}

		return true;
	}

	/**
	 * Check if positions are invalid compare with other placed ships.
	 * @param positions - positions of the current navire
	 * @param currentNavire - index of the current navire
	 * @return <code>true</code> if position is valide, <code>false</code> otherwise.
	 */
	private boolean checkPositionOtherNavires(
			int[][] positions, int currentNavire) {
		
		for (int i = 0; i < currentNavire; i++) {
			Navire n = this.joueur.getNavires().get(i);

			for (int j = 0; j < positions.length; j++) {
				if (n.positionContainsPoint(positions[j][0], positions[j][1])) {
					return false;
				}
			}
		}
		return true;
	}

	private boolean positionsAreAlign (int[][] positions) {
		if (positions.length == 1) {
			return true;
		}
		return positionsAreAlignX(positions) || positionsAreAlignY(positions);
	}

	private boolean positionsAreAlignX(int[][] positions) {
		for (int i = 1; i < positions.length; i++) {
			if (positions[i][0] != positions[i-1][0]) {
				return false;
			}
		}
		return true;
	}

	private boolean positionsAreAlignY(int[][] positions) {
		for (int i = 1; i < positions.length; i++) {
			if (positions[i][1] != positions[i-1][1]) {
				return false;
			}
		}
		return true;
	}

	private boolean shipIsAlign (int[][] positions) {

		if(positions.length == 1){
			return true;
		}

		int alignmt;
		if (positionsAreAlignY(positions)){
			alignmt=0;
		}else{
			alignmt=1;
		}

		int [] coord = new int[positions.length];

		for(int i=0; i<positions.length; i++){
			coord[i]=positions[i][alignmt];
		}

		Arrays.sort(coord, 0, coord.length);

		for(int i=0; i<coord.length-1; i++){

			if((coord[i]+1) != (coord[i+1])){
				return false;
			}

		}

		//System.out.println("Ship is aligned.");
		return true;
	}

}